#ifndef _SCENE_PROCESSOR_H
#define _SCENE_PROCESSOR_H

#define MAX_DEPTH 10000
#define FINGER_NUMBER 10
#define HAND_NUMBER 2

#include "global.h"
#include <vector>
#include "HandInfoTable.h"
#include "opencv2/imgproc/imgproc.hpp"
#include "opencv2/highgui/highgui.hpp"
#include "VSObject.h"
#include "ToolBox.h"
#include <opencv2/core/types_c.h>
using namespace std;

class SceneProcessor
{
public:
	SceneProcessor(void);
	~SceneProcessor(void);

public:
	void Init(XnUInt32 x,XnUInt32 y,double hfov,double vfov);
	void InitVar(xn::DepthMetaData &depthMD,xn::SceneMetaData &sceneMD,xn::ImageMetaData &imageMD);
	void getARBackground(Point3D zeroPlane,float* ground);
	void PreProcess();
	bool Detect(int appMode,bool calibrated);
	void Track();
	void Render4ChannelScene();
	void Render3ChannelScene();
	void Render4ChannelHand();
	void Render4ChannelLabelScene();
	void RenderTexture(int appmode);
	void getCameraCtrl(TrackData* lastData, TrackData* curData,int& dataCount);
	void getObjectCtrl(TrackData* lastData, TrackData* curData,int& dataCount);
	void getMenuCtrl(TrackData* lastData, TrackData* curData,int& dataCount);
	int hasHANDRECOG();
	Point3D getZeroPlane(int handIdx);
	void AddUser(int userId);
	void LostUser(int userId);
	void RenderHandpos();
	bool SelectVRObject(std::vector<VSObject>&,int dataCount,TrackData* curData,glm::mat4 transfer);
	bool SelectVRObject(std::vector<VSObject>&,int dataCount,TrackData* curData,ToolBox * toolBox,glm::mat4 transfer);
	bool SelectARObject(std::vector<VSObject>&,int dataCount,TrackData* curData, Point3D zeroPlane);
	bool SelectARObject(std::vector<VSObject>& objList,int dataCount,TrackData* curDataCtrl,ToolBox * toolBox, Point3D zeroPlane);
	bool isSameObject(int handIdx);
	std::string getDateTime(){return curDateTime;}
	void RenderFingertip(/*Point3D m_oglpos*/);
	int getHandAction(int handIdx){return m_pHandInfoTbl->getHandInfo(handIdx).getAction();}
	//test
	bool isSelect0Obj;

private:
	void morphology();
	void getHand();
	void createBalanceImg();
	bool checkAvlHand();
	bool getAction(cv::Mat &mat,int appMode,bool calibrated);
	bool getFingerAction(cv::Mat &mat,vector<vector<cv::Point> > cvHandContourPoints,std::vector<int> contourIdxs,
		HandInfoTable::HandInfo* hands,int & handscount,int appMode, bool calibrated);
	bool getSelectAction(cv::Mat &mat,vector<vector<cv::Point> > cvHandContourPoints,std::vector<int> contourIdxs,
		HandInfoTable::HandInfo* hands,int & handscount);
	int checkAction(HandInfoTable::HandInfo hand);
	int checkAction(HandInfoTable::HandInfo hand,HandInfoTable::HandInfo hole);
	
	void assignTexture();
	void drawTexture( float topLeftX, float topLeftY, float bottomRightX, float bottomRightY,int appmode );
	void getPlayerNo();

	void createDateTime();
	void createYUV();

private:
	static const int nColors = 10;

	int m_nPlayer;	// count the number of player
	bool m_bPlayerExist[nColors];
	int m_nMaxPlayer;	// count the max number of player

	int m_XRes;
	int m_YRes;
	int m_texWidth;
	int m_texHeight;
	GLfloat texcoords[8];
	double m_hfov;
	double m_vfov;

	float m_pDepthHis[MAX_DEPTH];
	unsigned char* m_pDepthTexBuf;
	unsigned char* m_pDepthTexBufRGBA;

	const XnDepthPixel* m_pDepth;
	const XnLabel* m_pLabels;
	const XnUInt8* m_pImage;
	XnPixelFormat m_format;

	GLuint m_depthTexID;
	GLuint m_depthTexIDRGBA;

	cv::Mat m_cvHand;
	cv::Mat m_cvImage;
	cv::Mat m_cvOldImage;
	cv::Mat m_cvTmp1;
	cv::Mat m_cvTmp2;
	cv::Mat m_cvTmp3;
	cv::Mat m_cvTmp4;
	cv::Mat m_cvSkin;

	double m_fingerAngle[FINGER_NUMBER*10];
	std::vector<double*> m_fingerLength;
	double m_handBoundingbox[HAND_NUMBER*2];

	TrackData * m_pcurTrack;
	TrackData * m_plastTrack;
	int m_moveSpdMax;

	int m_nframes;
	HandInfoTable * m_pHandInfoTbl;

	vector<cv::Point3d> handOglPos;
	vector<vector<cv::Point> > cvHandContourPoints;

	bool m_bImgBalance;

	// for output count
	int track1mat;
	std::vector<Point3D> m_oglpos;

	std::string curDateTime;

	Point3D m_zeroPlane;
	glm::mat4 m_camera_transfer;
};

#endif